﻿using System;
using HK.Core.GUIEx.Attribute;
using HK.Editor.GUIEx.Styles;
using HK.Editor.Serializable.Protocol.Drawer;
using HK.Editor.Utils;
using UnityEditor;
using UnityEngine;

namespace HK.Editor.Serializable.Drawer
{
    /// <summary>
    /// Drawer - MinMax(int)
    /// </summary>
    [CustomPropertyDrawer(typeof(IntMinMaxAttribute))]
    public class IntMinMaxDrawer : GUIPropertyDrawer<IntMinMaxAttribute>, IIntMinMaxDrawer
    {

        /// <summary>
        /// 最小值
        /// </summary>
        public int MinValue => SelfAttr?.Min ?? 0;
        
        /// <summary>
        /// 最大值
        /// </summary>
        public int MaxValue => SelfAttr?.Max ?? 0;

#region Draw

        /// <summary>
        /// 绘制标题
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iCaption">标题</param>
        /// <returns>绘制的矩形区域</returns>
        protected override Rect DrawCaption(Rect iRect, Event iEvent, GUIContent iCaption)
        {
            var displayRect = iRect;

            var captionRect = displayRect;
            captionRect.x += LabelIntent;
            captionRect.width *= 0.4f;
            var captionRectTmp = captionRect;
            captionRectTmp.y -= 1;
            // 绘制标题
            captionRectTmp = UtilsGUIEx.DrawLabel(captionRectTmp, iEvent, iCaption);

            var delBtnRect = displayRect;
            delBtnRect.x = captionRect.xMax;
            delBtnRect.width = BtnWidthIconOnly;
            delBtnRect = UtilsGUIEx.DrawButton(delBtnRect, iEvent, GuiExHelper.DelIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.intValue -= 1;
                        SelfProperty.intValue = Math.Max(MinValue, SelfProperty.intValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var addBtnRect = displayRect;
            addBtnRect.xMax -= HorizontalSpacing;
            addBtnRect.xMin = addBtnRect.xMax - BtnWidthIconOnly;
            addBtnRect = UtilsGUIEx.DrawButton(addBtnRect, iEvent, GuiExHelper.AddIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.intValue += 1;
                        SelfProperty.intValue = Math.Min(MaxValue, SelfProperty.intValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var intFieldRect = displayRect;
            intFieldRect.xMin = delBtnRect.xMax + HorizontalSpacing;
            intFieldRect.xMax = addBtnRect.xMin - HorizontalSpacing;
            intFieldRect.yMin = captionRectTmp.yMin;
            intFieldRect.yMax = captionRectTmp.yMax - VerticalSpacing;
            intFieldRect = DrawInputField(intFieldRect, iEvent, SelfProperty);
            
            return displayRect;
        }

        /// <summary>
        /// 绘制输入区域
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iProperty">输入Property</param>
        /// <returns>绘制的矩形区域</returns>
        private Rect DrawInputField(Rect iRect, Event iEvent, SerializedProperty iProperty)
        {
            var intFieldRect = iRect;
            if (null == iProperty) return intFieldRect;
            
            EditorGUI.BeginChangeCheck();
            var inputValue = EditorGUI.IntField(intFieldRect, SelfProperty.intValue);
            inputValue = Mathf.Clamp(inputValue, MinValue, MaxValue);
            
            if (EditorGUI.EndChangeCheck() && inputValue != SelfProperty.intValue)
            {
                SelfProperty.intValue = inputValue;
            }

            return intFieldRect;
        }

#endregion
        
    }

    /// <summary>
    /// Drawer - MinMax(intSlide)
    /// </summary>
    [CustomPropertyDrawer(typeof(IntSlideMinMaxAttribute))]
    public class IntSlideMinMaxDrawer : GUIPropertyDrawer<IntSlideMinMaxAttribute>, IIntSlideMinMaxDrawer
    {
        /// <summary>
        /// 最小值
        /// </summary>
        public int MinValue => SelfAttr?.Min ?? 0;
        
        /// <summary>
        /// 最大值
        /// </summary>
        public int MaxValue => SelfAttr?.Max ?? 0;
        
#region Draw

        /// <summary>
        /// 绘制标题
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iCaption">标题</param>
        /// <returns>绘制的矩形区域</returns>
        protected override Rect DrawCaption(Rect iRect, Event iEvent, GUIContent iCaption)
        {
            var displayRect = iRect;

            var captionRect = displayRect;
            captionRect.x += LabelIntent;
            captionRect.width *= 0.4f;
            var captionRectTmp = captionRect;
            captionRectTmp.y -= 1;
            // 绘制标题
            captionRectTmp = UtilsGUIEx.DrawLabel(captionRectTmp, iEvent, iCaption);

            var delBtnRect = displayRect;
            delBtnRect.x = captionRect.xMax;
            delBtnRect.width = BtnWidthIconOnly;
            delBtnRect = UtilsGUIEx.DrawButton(delBtnRect, iEvent, GuiExHelper.DelIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.intValue -= 1;
                        SelfProperty.intValue = Math.Max(MinValue, SelfProperty.intValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var addBtnRect = displayRect;
            addBtnRect.xMax -= HorizontalSpacing;
            addBtnRect.xMin = addBtnRect.xMax - BtnWidthIconOnly;
            addBtnRect = UtilsGUIEx.DrawButton(addBtnRect, iEvent, GuiExHelper.AddIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.intValue += 1;
                        SelfProperty.intValue = Math.Min(MaxValue, SelfProperty.intValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var intFieldRect = displayRect;
            intFieldRect.xMin = delBtnRect.xMax + HorizontalSpacing;
            intFieldRect.xMax = addBtnRect.xMin - HorizontalSpacing;
            intFieldRect.yMin = captionRectTmp.yMin;
            intFieldRect.yMax = captionRectTmp.yMax - VerticalSpacing;
            intFieldRect = DrawInputField(intFieldRect, iEvent, SelfProperty);
            
            return displayRect;
        }

        /// <summary>
        /// 绘制输入区域
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iProperty">输入Property</param>
        /// <returns>绘制的矩形区域</returns>
        protected virtual Rect DrawInputField(Rect iRect, Event iEvent, SerializedProperty iProperty)
        {
            var intFieldRect = iRect;
            if (null == iProperty) return intFieldRect;
            
            EditorGUI.BeginChangeCheck();
            var inputValue = EditorGUI.IntSlider(intFieldRect, SelfProperty.intValue, MinValue, MaxValue);
            inputValue = Mathf.Clamp(inputValue, MinValue, MaxValue);
            
            if (EditorGUI.EndChangeCheck() && inputValue != SelfProperty.intValue)
            {
                SelfProperty.intValue = inputValue;
            }

            return intFieldRect;
        }

#endregion
        
    }
    
    /// <summary>
    /// Drawer - MinMax(int)
    /// </summary>
    [CustomPropertyDrawer(typeof(LongMinMaxAttribute))]
    public class LongMinMaxDrawer : GUIPropertyDrawer<LongMinMaxAttribute>, ILongMinMaxDrawer
    {

        /// <summary>
        /// 最小值
        /// </summary>
        public long MinValue => SelfAttr?.Min ?? 0;
        
        /// <summary>
        /// 最大值
        /// </summary>
        public long MaxValue => SelfAttr?.Max ?? 0;

#region Draw

        /// <summary>
        /// 绘制标题
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iCaption">标题</param>
        /// <returns>绘制的矩形区域</returns>
        protected override Rect DrawCaption(Rect iRect, Event iEvent, GUIContent iCaption)
        {
            var displayRect = iRect;

            var captionRect = displayRect;
            captionRect.x += LabelIntent;
            captionRect.width *= 0.4f;
            var captionRectTmp = captionRect;
            captionRectTmp.y -= 1;
            // 绘制标题
            captionRectTmp = UtilsGUIEx.DrawLabel(captionRectTmp, iEvent, iCaption);

            var delBtnRect = displayRect;
            delBtnRect.x = captionRect.xMax;
            delBtnRect.width = BtnWidthIconOnly;
            delBtnRect = UtilsGUIEx.DrawButton(delBtnRect, iEvent, GuiExHelper.DelIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.longValue -= 1L;
                        SelfProperty.longValue = Math.Max(MinValue, SelfProperty.longValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var addBtnRect = displayRect;
            addBtnRect.xMax -= HorizontalSpacing;
            addBtnRect.xMin = addBtnRect.xMax - BtnWidthIconOnly;
            addBtnRect = UtilsGUIEx.DrawButton(addBtnRect, iEvent, GuiExHelper.AddIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.longValue += 1L;
                        SelfProperty.longValue = Math.Min(MaxValue, SelfProperty.longValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var intFieldRect = displayRect;
            intFieldRect.xMin = delBtnRect.xMax + HorizontalSpacing;
            intFieldRect.xMax = addBtnRect.xMin - HorizontalSpacing;
            intFieldRect.yMin = captionRectTmp.yMin;
            intFieldRect.yMax = captionRectTmp.yMax - VerticalSpacing;
            intFieldRect = DrawInputField(intFieldRect, iEvent, SelfProperty);
            
            return displayRect;
        }

        /// <summary>
        /// 绘制输入区域
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iProperty">输入Property</param>
        /// <returns>绘制的矩形区域</returns>
        private Rect DrawInputField(Rect iRect, Event iEvent, SerializedProperty iProperty)
        {
            var intFieldRect = iRect;
            if (null == iProperty) return intFieldRect;
            
            EditorGUI.BeginChangeCheck();
            var inputValue = EditorGUI.LongField(intFieldRect, SelfProperty.longValue);
            inputValue = Math.Max(inputValue, MinValue);
            inputValue = Math.Min(inputValue, MaxValue);
            
            if (EditorGUI.EndChangeCheck() && inputValue != SelfProperty.longValue)
            {
                SelfProperty.longValue = inputValue;
            }

            return intFieldRect;
        }

#endregion
        
    }
    
    
    
    /// <summary>
    /// Drawer - MinMax(float)
    /// </summary>
    [CustomPropertyDrawer(typeof(FloatMinMaxAttribute))]
    public class FloatMinMaxDrawer : GUIPropertyDrawer<FloatMinMaxAttribute>, IFloatMinMaxDrawer
    {

        /// <summary>
        /// 最小值
        /// </summary>
        public float MinValue => SelfAttr?.Min ?? 0.0f;
        
        /// <summary>
        /// 最大值
        /// </summary>
        public float MaxValue => SelfAttr?.Max ?? 0.0f;

#region Draw

        /// <summary>
        /// 绘制标题
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iCaption">标题</param>
        /// <returns>绘制的矩形区域</returns>
        protected override Rect DrawCaption(Rect iRect, Event iEvent, GUIContent iCaption)
        {
            var displayRect = iRect;

            var captionRect = displayRect;
            captionRect.x += LabelIntent;
            captionRect.width *= 0.4f;
            var captionRectTmp = captionRect;
            captionRectTmp.y -= 1;
            // 绘制标题
            captionRectTmp = UtilsGUIEx.DrawLabel(captionRectTmp, iEvent, iCaption);

            var delBtnRect = displayRect;
            delBtnRect.x = captionRect.xMax;
            delBtnRect.width = BtnWidthIconOnly;
            delBtnRect = UtilsGUIEx.DrawButton(delBtnRect, iEvent, GuiExHelper.DelIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.floatValue -= 1.0f;
                        SelfProperty.floatValue = Mathf.Max(MinValue, SelfProperty.floatValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var addBtnRect = displayRect;
            addBtnRect.xMax -= HorizontalSpacing;
            addBtnRect.xMin = addBtnRect.xMax - BtnWidthIconOnly;
            addBtnRect = UtilsGUIEx.DrawButton(addBtnRect, iEvent, GuiExHelper.AddIconBtn,
                () =>
                {
                    if (null != SelfProperty)
                    {
                        SelfProperty.floatValue += 1.0f;
                        SelfProperty.floatValue = Mathf.Min(MaxValue, SelfProperty.floatValue);
                    }
                }, Color.clear, GuiExHelper.PreButton);

            var intFieldRect = displayRect;
            intFieldRect.xMin = delBtnRect.xMax + HorizontalSpacing;
            intFieldRect.xMax = addBtnRect.xMin - HorizontalSpacing;
            intFieldRect.yMin = captionRectTmp.yMin;
            intFieldRect.yMax = captionRectTmp.yMax - VerticalSpacing;
            intFieldRect = DrawInputField(intFieldRect, iEvent, SelfProperty);
            
            return displayRect;
        }

        /// <summary>
        /// 绘制输入区域
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iProperty">输入Property</param>
        /// <returns>绘制的矩形区域</returns>
        private Rect DrawInputField(Rect iRect, Event iEvent, SerializedProperty iProperty)
        {
            var intFieldRect = iRect;
            if (null == iProperty) return intFieldRect;
            
            EditorGUI.BeginChangeCheck();
            var inputValue = EditorGUI.FloatField(intFieldRect, SelfProperty.floatValue);
            inputValue = Mathf.Clamp(inputValue, MinValue, MaxValue);
            
            if (EditorGUI.EndChangeCheck() && Math.Abs(inputValue - SelfProperty.floatValue) > Mathf.Epsilon)
            {
                SelfProperty.floatValue = inputValue;
            }

            return intFieldRect;
        }

#endregion
        
    }
}
